﻿// (C) SocketCoder.Com 
// SocketCoder Silverlight Media Streaming 
// Last Modify: 31/5/2014
// Note: This Project is just some simple samples, if you are looking for a production solution Visit 
// SocketCoder.Com to Buy The Full WCS Web Conferencing Solution Source Code. 
//
namespace MediaStreaming
{
    using System;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Ink;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using NSpeex;

    public class SpeexEncoderDecoder
    {
        SpeexEncoder CodecSpeexEncoder = new SpeexEncoder(BandMode.Wide);
        SpeexDecoder CodecSpeexDecoder = new SpeexDecoder(BandMode.Wide);


        private int _VoiceQuality = 5;

        public int VoiceQuality
        {
            set
            {
                _VoiceQuality = this.CodecSpeexEncoder.Quality = value;
            }
            get
            {
                return _VoiceQuality;
            }
        }

        public SpeexEncoderDecoder()
        {
            this.CodecSpeexEncoder.Quality = _VoiceQuality;
        }

        public byte[] Decode(byte[] encodedData, int SamplesPerSecond, int Channels)
        {
            try
            {
                // Read Len Header
                byte[] LengthHeader = new byte[10];
                Buffer.BlockCopy(encodedData, 0, LengthHeader, 0, LengthHeader.Length);
                int PacketLen = int.Parse(System.Text.UnicodeEncoding.UTF8.GetString(LengthHeader, 0, LengthHeader.Length));
                byte[] PacketBytes = new byte[PacketLen];
                Buffer.BlockCopy(encodedData, LengthHeader.Length, PacketBytes, 0, PacketLen);

                // Decode Data
                short[] decodedFrame = new short[SamplesPerSecond * Channels];
                int decodedBytes = CodecSpeexDecoder.Decode(PacketBytes, 0, PacketBytes.Length, decodedFrame, 0, false);

                byte[] decodedAudioData = null;

                decodedAudioData = new byte[decodedBytes * 2];

                try
                {
                    for (int shortIndex = 0, byteIndex = 0; shortIndex < decodedBytes; shortIndex++, byteIndex += 2)
                    {
                        byte[] temp = BitConverter.GetBytes(decodedFrame[shortIndex]);
                        decodedAudioData[byteIndex] = temp[0];
                        decodedAudioData[byteIndex + 1] = temp[1];
                    }
                }
                catch
                {
                    return decodedAudioData;
                }
                return decodedAudioData;
            }
            catch
            {
                return new byte[0];
            }
        }

        public byte[] Encode(byte[] rawData)
        {
            try
            {
                var inDataSize = rawData.Length / 2;

                var inData = new short[inDataSize];

                for (int index = 0; index < rawData.Length; index += 2)
                {
                    inData[index / 2] = BitConverter.ToInt16(rawData, index);
                }
                inDataSize = inDataSize - inDataSize % CodecSpeexEncoder.FrameSize;
                var encodedData = new byte[rawData.Length];
                var encodedBytes = CodecSpeexEncoder.Encode(inData, 0, inDataSize, encodedData, 0, encodedData.Length);
                byte[] encodedAudioData = null;
                if (encodedBytes != 0)
                {
                    encodedAudioData = new byte[encodedBytes];
                    Array.Copy(encodedData, 0, encodedAudioData, 0, encodedBytes);
                }

                return AddLenHeaderToData(encodedAudioData);
            }
            catch { return new byte[0]; }
        }

        private byte[] AddLenHeaderToData(byte[] EncodedData)
        {
            try
            {
                if (EncodedData.Length > 0)
                {
                    // The First 10 Bytes is the Packet Length
                    string PacketLenString = EncodedData.Length.ToString();
                    string Zero = "";
                    while (PacketLenString.Length + Zero.Length < 10)
                    {
                        Zero += "0";
                    }
                    PacketLenString = Zero + PacketLenString;
                    byte[] LenBytes = System.Text.UnicodeEncoding.UTF8.GetBytes(PacketLenString);

                    return AppendPayloadArray(LenBytes, EncodedData);
                }

                return new byte[0];
            }
            catch { return new byte[0]; }
        }

        private Byte[] AppendPayloadArray(Byte[] FirstBuffer, Byte[] SecondBuffer)
        {
            try
            {
                Byte[] FinalArr = new Byte[FirstBuffer.Length + SecondBuffer.Length];
                Buffer.BlockCopy(FirstBuffer, 0, FinalArr, 0, FirstBuffer.Length);
                Buffer.BlockCopy(SecondBuffer, 0, FinalArr, FirstBuffer.Length, SecondBuffer.Length);
                return FinalArr;
            }
            catch { return new Byte[0]; }
        }

    }
    internal static class Converters
    {
        public static byte[] ToByteArray(this short[] array)
        {
            byte[] dst = new byte[array.Length * 2];
            Buffer.BlockCopy(array, 0, dst, 0, dst.Length);
            return dst;
        }

        public static short[] ToShortArray(this byte[] array)
        {
            short[] dst = new short[array.Length / 2];
            Buffer.BlockCopy(array, 0, dst, 0, array.Length);
            return dst;
        }
    }

}